package com.xfc.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xfc.common.core.redis.RedisCache;
import com.xfc.config.MyAESUtil;
import com.xfc.config.Result;
import com.xfc.config.Tools;
import com.xfc.config.sms.SmsSend;
import com.xfc.school.domain.ScStudent;
import com.xfc.school.domain.ScTeacher;
import com.xfc.school.service.IScStudentService;
import com.xfc.school.service.IScTeacherService;
import com.xfc.wx.domain.ScSms;
import com.xfc.wx.domain.ScWxUser;
import com.xfc.wx.service.IScSmsService;
import com.xfc.wx.service.IScWxUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 *  微信登录
 * @author lcj
 */
@Slf4j
@RestController
@Api(tags = "微信登录")
@Validated
@RequestMapping("/wx")
public class WxLoginController {


    @Autowired
    private RedisCache redisUtils;

    @Autowired
    private IScWxUserService wxUserService;

    @Autowired
    private IScTeacherService teacherService;

    @Autowired
    private SmsSend sendService;

    @Autowired
    private IScSmsService smsService;

    @Autowired
    private IScStudentService studentService;

    @Autowired
    private WxMpService wxMpService;


    /**微信appid*/
    @Value("${wx.mp.appid}")
    private String appid;

    /**微信秘钥*/
    @Value("${wx.mp.secret}")
    private String secret;

    /**短信模板*/
    @Value("${sms.templateId.a}")
    private int tema;

    /**预约短信模板*/
    @Value("${sms.templateId.b}")
    private int temb;



    /**
     *  用户微信获取
     * @return 返回token
     */
    @GetMapping("/login")
    @ApiOperation(value = "用户微信获取")
    @ApiImplicitParams({
            @ApiImplicitParam( name = "code", value =  "微信code",  dataType = "String",required = true),
            @ApiImplicitParam( name = "type", value =  "老师/会员",  dataType = "String",required = true)
    })
    public Result<?> login(@NotBlank @RequestParam String code,String type) throws Exception {
        //获取AuthToken
        log.info("code：{}",code);
        String openId=this.getOpenid(code);
        if (StringUtils.isEmpty(openId)){
            return Result.error("获取openid失败");
        }
        //查询数据库中是否存在用户信息
        QueryWrapper<ScWxUser> queryWrapper=new QueryWrapper<ScWxUser>().eq("open_id",openId);
        ScWxUser user=wxUserService.getOne(queryWrapper);
        ScWxUser user1=new ScWxUser();
        Map<String,String> map=new HashMap<>(2);
        //判断用户是否存在
        if (Objects.isNull(user)){
            //存储用户openid
            user1.setOpenId(openId);
            wxUserService.save(user1);
            map.put("token",null);
            map.put("openId",openId);
        }else {
            if (StringUtils.isEmpty(user.getMobile())) {
                map.put("token", null);
                map.put("openId", openId);
            } else{
                user1.setId(user.getId());
                user1.setLastLoginTime(user.getLoginTime());
                user1.setLoginTime(new Date());
                //token信息
                String token = user.getMobile() + ",px_" + System.currentTimeMillis();
                //参数加密
                String res= MyAESUtil.Encrypt(token,Tools.USER_KRY);
                //将用户信息存入redis
                redisUtils.setCacheObject(Tools.USER_TOKEN + user.getMobile(), user, 30, TimeUnit.DAYS);
                wxUserService.updateById(user1);
                map.put("token", res);
                map.put("openId", openId);
                //不为空则为老师
                if (StringUtils.isNotEmpty(type)){
                    QueryWrapper<ScTeacher> queryWrapper1=new QueryWrapper<>();
                    queryWrapper1.eq("teacher_mobile",user.getMobile());
                    queryWrapper1.eq("state",0);
                    //查询老师是否存在
                    ScTeacher scTeacher=teacherService.getOne(queryWrapper1);
                    if (Objects.isNull(scTeacher)){
                        map.put("token", null);
                    }
                    map.put("type","teacher");
                }else {
                    //查询手机号是否是学生手机号
                    List<ScStudent> student=studentService.list(new QueryWrapper<ScStudent>().eq("student_mobile",user.getMobile()).or().eq("student_mobile2",user.getMobile()));
                    if (student.size()==0){
                        map.put("token", null);
                    }
                    map.put("type","student");
                }
            }
        }
        return Result.ok(map);
    }




    /**
     *  用户注册
     */
    @PostMapping("/register")
    @ApiOperation(value = "用户注册")
    @ApiImplicitParams({
            @ApiImplicitParam( name = "mobile", value =  "手机号",  dataType = "String",required = true),
            @ApiImplicitParam( name = "code", value =  "验证码",  dataType = "String",required = true),
            @ApiImplicitParam( name = "openId", value =  "openId",  dataType = "String",required = true),
            @ApiImplicitParam( name = "type", value =  "老师/用户",  dataType = "String"),
    })
    public Result<?> register(@NotBlank @RequestParam String mobile,
                           @NotNull @RequestParam Integer code,
                           @NotBlank @RequestParam String openId, String type) throws Exception {
        Map<String,String> map=new HashMap<>(2);
        //验证验证码
        Integer redisCode=redisUtils.getCacheObject(Tools.SMS_CODE+mobile);
        if (!Objects.equals(code, redisCode)){
            return Result.error("验证码不正确");
        }
        ScWxUser wxUser=wxUserService.getOne(new QueryWrapper<ScWxUser>().eq("open_id",openId));
        if (Objects.isNull(wxUser)){
            return Result.error("没有查询到openId");
        }
        wxUser.setMobile(mobile);
        wxUser.setCreateTime(new Date());
        if (StringUtils.isNotEmpty(type)){
            //手机号查询
            ScTeacher scTeacher=teacherService.getOne(new QueryWrapper<ScTeacher>().eq("state",0).eq("teacher_mobile",mobile));
            //查询结果是老师
            if (Objects.nonNull(scTeacher)){
                wxUser.setEmployee(1);
                wxUser.setName(Objects.isNull(scTeacher.getTeacherName())?"":scTeacher.getTeacherName());
                map.put("type","teacher");
            }else {
                return Result.error("请输入正确的手机号");
            }
        } else{
            //查询手机号是否是学生手机号
            List<ScStudent> student=studentService.list(new QueryWrapper<ScStudent>().eq("state",0).eq("student_mobile",mobile).or().eq("student_mobile2",wxUser.getMobile()));
            if (student.size()==0){
                return Result.error("请输入正确的手机号");
            }
            wxUser.setName(Objects.isNull(student.get(0).getParentName())?"":student.get(0).getParentName());
            wxUser.setEmployee(0);
            map.put("type","student");
        }
        //查询是否有重复新手机号
        QueryWrapper<ScWxUser> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("mobile",mobile);
        ScWxUser scWxUser=wxUserService.getOne(queryWrapper);
        if (Objects.nonNull(scWxUser)){
            wxUserService.removeById(scWxUser.getId());
        }
        wxUserService.saveOrUpdate(wxUser);
        //token信息
        String token=wxUser.getMobile()+",px_"+System.currentTimeMillis();
        //参数加密
        String res= MyAESUtil.Encrypt(token,Tools.USER_KRY);
        //将用户信息存入redis
        redisUtils.setCacheObject(Tools.USER_TOKEN+wxUser.getMobile(),wxUser,30, TimeUnit.DAYS);
        map.put("token", res);
        map.put("openId", wxUser.getOpenId());
        return Result.ok("注册成功",map);
    }



    /**
     *  发送验证码
     */
    @GetMapping("/sendCode")
    @ApiOperation(value = "发送验证码")
    @ApiImplicitParams({
            @ApiImplicitParam( name = "mobile", value =  "手机号",  dataType = "String",required = true),
            @ApiImplicitParam( name = "openId", value =  "openid",  dataType = "String",required = true),
            @ApiImplicitParam( name = "type", value =  "老师/学生",  dataType = "String",required = true)
    })
    public Result<?> sendCode(@NotBlank @RequestParam String mobile, @NotBlank @RequestParam String openId
            ,  String type) {

        QueryWrapper<ScWxUser> queryWrapperUser=new QueryWrapper<>();
        queryWrapperUser.eq("open_id",openId);
        ScWxUser wxUser=wxUserService.getOne(queryWrapperUser);
        if (Objects.isNull(wxUser)){
            return Result.error("没有查询到用户信息");
        }
        if (StringUtils.isNotEmpty(type)){
            ScTeacher scTeacher=teacherService.getOne(new QueryWrapper<ScTeacher>().eq("teacher_mobile",mobile));
            //查询结果是老师
            if (Objects.isNull(scTeacher)){
                 return Result.error("此手机号没有录入系统");
            }
        }else {
            //查询手机号是否是学生手机号
            List<ScStudent> student=studentService.list(new QueryWrapper<ScStudent>().eq("student_mobile",mobile).or().eq("student_mobile2",mobile));
            if (student.size()==0){
                return Result.error("此手机号没有录入系统");
            }
        }
        //查询短信条数
        QueryWrapper<ScSms> queryWrapper=new QueryWrapper<>();
        queryWrapper.apply(true, "TO_DAYS(NOW())-TO_DAYS(create_time) = 0");
        queryWrapper.eq("open_id",openId);
        int smsNum=smsService.count(queryWrapper);
        if (Tools.SMS_NUM<smsNum){
            return Result.error("短信发送条数已上线");
        }
        //短信发送
        boolean status=sendService.send(mobile,tema,openId);
        if (status){
            return Result.ok("发送成功");
        }
        return Result.error("短信发送异常");
    }

    /**
     *  发送预约验证码
     */
    @GetMapping("/sendReservationCode")
    @ApiOperation(value = "发送预约验证码")
    @ApiImplicitParams({
            @ApiImplicitParam( name = "mobile", value =  "手机号",  dataType = "String",required = true),
            @ApiImplicitParam( name = "openId", value =  "openid",  dataType = "String",required = true)
    })
    public Result<?> sendReservationCode(@NotBlank @RequestParam String mobile, @NotBlank @RequestParam String openId) {

        //查询短信条数
        QueryWrapper<ScSms> queryWrapper=new QueryWrapper<>();
        queryWrapper.apply(true, "TO_DAYS(NOW())-TO_DAYS(create_time) = 0");
        queryWrapper.eq("open_id",openId);
        int smsNum=smsService.count(queryWrapper);
        if (Tools.SMS_NUM<smsNum){
            return Result.error("短信发送条数已上线");
        }
        //短信发送
        boolean status=sendService.send(mobile,temb,openId);
        if (status){
            return Result.ok("发送成功");
        }
        return Result.error("短信发送异常");
    }


    /**
     * 根据code获取openId
     * @param code  code
     * @return String
     */
    public String getOpenid(String code) {
        try {
            WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code);
            WxMpUser user = wxMpService.oauth2getUserInfo(accessToken, null);
            return user.getOpenId();
        } catch (WxErrorException e) {
            // 处理异常
            log.error(e.getMessage());
            return null;
        }
    }


}
